import static pl.edu.agh.transstat.parsing.ConfigurationTags.DEV;
import static pl.edu.agh.transstat.parsing.ConfigurationTags.MAX;
import static pl.edu.agh.transstat.parsing.ConfigurationTags.MEAN;
import static pl.edu.agh.transstat.parsing.ConfigurationTags.MEDIAN;
import static pl.edu.agh.transstat.parsing.ConfigurationTags.MIN;

import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


import pl.edu.agh.transstat.displaying.Chart;
import pl.edu.agh.transstat.displaying.TableGenerator;
import pl.edu.agh.transstat.parsing.ConfigurationParser;
import pl.edu.agh.transstat.parsing.FileParser;
import pl.edu.agh.transstat.parsing.ResultXmlParser;
import pl.edu.agh.transstat.parsing.SimulationConfigurationParser;
import pl.edu.agh.transstat.parsing.StatData;
import pl.edu.agh.transstat.simulation.Configuration;
import pl.edu.agh.transstat.simulation.Simulation;
import pl.edu.agh.transstat.statictisc.Function;
import pl.edu.agh.transstat.statictisc.Max;
import pl.edu.agh.transstat.statictisc.Mean;
import pl.edu.agh.transstat.statictisc.Median;
import pl.edu.agh.transstat.statictisc.Min;
import pl.edu.agh.transstat.statictisc.StandardDeviation;

public class Main {

	private List<Simulation> simulations;
	private String filename;
	private Map<String,Configuration> confs;
	
	public Main(String filename) {
		simulations = new ArrayList<Simulation>();
		this.filename = filename;
	}

	public void start() {
		// for each folder
		ConfigurationParser conf = new ConfigurationParser(filename);
		SimulationConfigurationParser parser = new SimulationConfigurationParser("conf");
		confs = parser.getData();
		
		List<StatData> sdata = conf.getData();
		String path = conf.getDirPath();
		List<String> paths = conf.getPaths(path, "xls");
		for (String dir : paths) {
			Map<String, List<Double>> data = parseFiles(dir);
			String[] name = dir.split("\\\\");	
			String fileNameWithExt = name[name.length-1];
			simulations.add(new Simulation(data, fileNameWithExt));
			
			//find the config for this results and mark it to be printed
			String[] nameSep = fileNameWithExt.split("\\.");
			String fileName = nameSep[0];
			for (int i=1; i<nameSep.length-1; i++)
				 fileName += "." + nameSep[i];
			Configuration config = confs.get(fileName);
			if (config == null){
				System.out.println("The configuration file for simulation results " + fileName + " is not present. Make sure this configuration file is in config directory.");
				return;
			}
			config.setPrint(true);
		}

		for (StatData d : sdata) {			
			List<String> params;
			if(d.isAllParams())
				params = new ArrayList<String>(simulations.get(0).getResults().keySet());
			else
				params = d.getParams();

			List<Function> functions;
			if(d.isAllFunctions()){
				functions = getFunctions();				
			} else {
				functions = getFunctions(d.getFunctions());
			}
			
			generateCharts(functions, params, d.isOneChart());
		}
		
		generateTables();
	}

	private void generateTables() {
		new TableGenerator(confs).generate();
	}

	private Map<String, List<Double>> parseFiles(String dir) {
		Map<String, List<Double>> results = new FileParser(dir).getResults();
		results.putAll(parseMeasureFile(dir));
		return results;
	}

	private Map<String, List<Double>> parseMeasureFile(String dir) {
		//create file name with proper extension
		String temp[] = dir.split("\\.");
		StringBuilder measureName = new StringBuilder();
		for (int i=0;i<temp.length-1;i++)
			measureName.append(temp[i] + ".");
		measureName.append("xls_measures.xml");
		
		//if there is no measure file, return empty map
		if (!new File(measureName.toString()).exists())
			return new HashMap<String,List<Double>>();
		
		return new ResultXmlParser(measureName.toString()).getData().getResults();
		
	}

	private void generateCharts(List<Function> functions, List<String> params, boolean oneChart) {
		Chart chart = new Chart();
		chart.plot(simulations, functions, params, oneChart);

	}

	private List<Function> getFunctions() {
		List<Function> functions = new ArrayList<Function>();
		functions.add(new Mean());
		functions.add(new Max());
		functions.add(new Min());
		functions.add(new Median());
		functions.add(new StandardDeviation());
		return functions;
	}

	private List<Function> getFunctions(List<String> functionsNames) {
		List<Function> functions = new ArrayList<Function>();
		if(functionsNames.contains(MEAN))	functions.add(new Mean());
		if(functionsNames.contains(MAX))	functions.add(new Max());
		if(functionsNames.contains(MIN))	functions.add(new Min());
		if(functionsNames.contains(MEDIAN))	functions.add(new Median());
		if(functionsNames.contains(DEV))	functions.add(new StandardDeviation());
		return functions;
	}

	public static void main(String[] args) {
		if (args.length < 1)
			System.out.println("Please provide the path to the configuration file");
		new Main(args[0]).start();
	}

}
